# -*- coding: utf-8 -*-
# @Time    : 2022/3/2 3:06 PM
# @Author  : zhongxin
# @Email   : 490336534@qq.com
# @File    : conftest.py
import inspect
import os
import time

import allure
import pytest

from src.pages.HomePage import HomePage
from src.utils.allureoperator import attach_png
from src.utils.constant import TEST_PIC, ROBOT, UDID, APK_PATH, PERF_PATH, REPORT_PATH, REMOTE_URL
from src.utils.dataoperator import DataOperator
from src.utils.fileoperator import FileOperator
from src.utils.jsonoperator import JsonOperator
from src.utils.logoperator import LogOperator
from src.utils.perf.cpu import CpuMonitor
from src.utils.perf.flow import TrafficMonitor
from src.utils.perf.fps import FPSMonitor
from src.utils.perf.memory import MemMonitor
from src.utils.perf.power import PowerMonitor
from src.utils.perf.thread_num import ThreadNumMonitor
from src.utils.reportoperator import ReportOperator
from src.utils.timeoperator import timeoperator

logger = LogOperator(__name__)


@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """
    pytest 失败后执行
    :param item: 测试用例
    :param call: 测试步骤
    :return:
    """
    out = yield
    result = out.get_result()
    logger.info(f"测试报告:{result}")
    logger.info(f"执行耗时:{call.duration}")
    if result.outcome in ['failed', 'error']:
        for k, v in item.funcargs.items():
            try:
                if hasattr(v, 'driver'):
                    attach_png(f'{TEST_PIC}/{int(time.time())}.png', "失败截图", v)
                    break
            except Exception as e:
                logger.error(f"失败截图异常:{e}")


def pytest_assume_fail(lineno, entry):
    """
    assume 断言报错截图
    """
    print(entry)
    for i in inspect.stack():
        if os.path.split(i.filename)[1].startswith('test_'):
            try:
                for k, v in i.frame.f_locals.items():
                    if hasattr(v, 'driver'):
                        attach_png(f'{TEST_PIC}/{int(time.time())}.png', f"失败截图_{int(time.time())}", v)
                        break
            except Exception:
                pass


def pytest_terminal_summary(terminalreporter, exitstatus, config):
    """
    统计测试结果
    :param terminalreporter:
    :param exitstatus:
    :param config:
    :return:
    """
    logger.info(f"总计:{terminalreporter._numcollected}")
    stats = terminalreporter.stats
    failed_num = len(stats.get('failed', []))
    error_num = len(stats.get('error', []))
    logger.info(f"通过:{len(stats.get('passed', []))}")
    logger.info(f"失败:{failed_num}")
    logger.info(f"异常:{error_num}")
    logger.info(f"跳过:{len(stats.get('skipped', []))}")
    duration = time.time() - terminalreporter._sessionstarttime
    logger.info(f"总耗时:{duration}秒")
    if not hasattr(config, "workerinput"):
        jsonoperator = JsonOperator()
        allure_results = jsonoperator.get_allure_result()
        if failed_num + error_num > 0:
            if ROBOT:
                try:
                    r = ReportOperator(hook=ROBOT.split(','))
                    result_str = '\n'.join([
                        f"通过:{len(stats.get('passed', []))}",
                        f"失败:{len(stats.get('failed', []))}",
                        f"异常:{len(stats.get('error', []))}",
                        f"跳过:{len(stats.get('skipped', []))}",
                        f"耗时:{duration:.2f}秒",
                    ])
                    try:
                        passed_list, failed_list, error_list, skipped_list = r.change_run_detail(allure_results)
                        if len(failed_list):
                            result_str += '\n\n失败用例:\n'
                            result_str += '\n'.join(failed_list)
                        if len(error_list):
                            result_str += '\n\n异常用例:\n'
                            result_str += '\n'.join(error_list)
                    except Exception as e:
                        logger.error(e)
                    r.send_msg(result_str)
                except Exception as e:
                    logger.error(e)


def pytest_collection_modifyitems(session, items):
    """
    修改用例执行顺序
    :param session: 会话信息
    :param items: 用例列表
    :return:
    """
    for item in items:
        item.name = item.name.encode("utf-8").decode("unicode_escape")
        item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape")
    logger.info(f"收集到的测试用例:{items}")


@pytest.fixture(scope="session", autouse=True)
def performance():
    """
    统计设备cpu情况
    @return:
    """
    if "127.0.0.1" in REMOTE_URL:
        app = "com.greenline.guahao"
        t = timeoperator.strftime_now("%Y_%m_%d_%H_%M_%S")
        frequency = 5

        cpu_monitor = CpuMonitor(UDID, [app], frequency)
        traffic_monitor = TrafficMonitor(UDID, [app], frequency)
        fps_monitor = FPSMonitor(UDID, app, frequency)
        mem_monitor = MemMonitor(UDID, [app], frequency)
        power_monitor = PowerMonitor(UDID, frequency)
        thread_num_monitor = ThreadNumMonitor(UDID, app, frequency)

        cpu_monitor.start(t)
        traffic_monitor.start(t)
        fps_monitor.start(t)
        mem_monitor.start(t)
        power_monitor.start(t)
        thread_num_monitor.start(t)
        yield
        cpu_monitor.stop()
        traffic_monitor.stop()
        fps_monitor.stop()
        mem_monitor.stop()
        power_monitor.stop()
        thread_num_monitor.stop()
        try:
            r = ReportOperator(hook=ROBOT.split(','))
            d = DataOperator()
            r.send_msg(d.all_handle())
        except Exception as e:
            logger.error(e)
        FileOperator.rename_folder(PERF_PATH, os.path.join(REPORT_PATH, f'perf_{timeoperator.now4}'))
    else:
        logger.error("执行手机与电脑直连才进行性能数据统计")
        yield


@pytest.fixture(scope='module')
def home():
    home = HomePage()
    url = "https://wy.guahao.com"
    with allure.step(f"打开浏览器进入「{url}」"):
        home.open(url, home.registered)
    yield home
    home.close()


@pytest.fixture(scope='session')
def install_apk():
    """
    安装APP
    """
    wy = HomePage()
    wy.install_apk(sys='android', udid=UDID, app='wy', apk=APK_PATH)


@pytest.fixture(scope='module')
def home_android(install_apk):
    home = HomePage(file_name="home_android")
    with allure.step(f"打开微医APP"):
        home.open_phone(sys='android', udid=UDID, app='wy')
        home.close_dialog(expect_text="微医")
        home.click(home.home_index)
        time.sleep(2)
    yield home
    home.close()
